package cn.lg.soar.common.util.jackson;

import cn.lg.soar.common.util.jackson.annotations.Deserializer;
import cn.lg.soar.common.util.jackson.annotations.Serializer;
import cn.lg.soar.common.util.jackson.deserializer.DecimalDeserializer;
import cn.lg.soar.common.util.jackson.deserializer.SDateDeserializer;
import cn.lg.soar.common.util.jackson.deserializer.SLocalDateDeserializer;
import cn.lg.soar.common.util.jackson.deserializer.SLocalDateTimeDeserializer;
import cn.lg.soar.common.util.jackson.serializer.*;
import cn.lg.soar.common.util.reflect.ReflectUtil;
import cn.lg.soar.common.util.reflect.SoarBeanUtils;
import cn.lg.soar.common.util.trans.annotations.Translate;
import cn.lg.soar.common.util.trans.annotations.TranslateName;
import cn.lg.soar.common.util.trans.handler.ITranslateHandler;
import cn.lg.soar.common.util.trans.jackson.TranslateSerializer;
import cn.lg.soar.common.util.trans.model.TranslateContext;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;

import java.lang.annotation.Annotation;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 功能描述: 自定义项目内省器 <br/>
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class ProjectJacksonAnnotationIntrospector extends JacksonAnnotationIntrospector {

    /**
     * @param am 带注释字段
     * @return "java.lang.Object"
     */
    @Override
    public Object findSerializer(Annotated am) {
        if (am instanceof AnnotatedMember) {
            Class<?> rawType = am.getRawType();
            AnnotatedMember annotatedMember = (AnnotatedMember) am;
            Iterable<Annotation> annotationIterable = annotatedMember.getAllAnnotations().annotations();
            List<Annotation> annotationList = new ArrayList<>();
            annotationIterable.forEach(annotationList::add);
            Annotation[] annotations = annotationList.toArray(new Annotation[0]);
            for (Annotation annotation : annotations) {
                // 增强序列化
                Serializer serializer = getAnnotation(Serializer.class, annotation);
                if (serializer != null) {
                    PlusSerializer jsonSerializer = ReflectUtil.newInstance(serializer.value());
                    jsonSerializer.init(annotation, am);
                    return jsonSerializer;
                }
                // 翻译
                Translate translate = getAnnotation(Translate.class, annotation);
                if (translate != null) {
                    ITranslateHandler<?> handler = SoarBeanUtils.getBean(translate.value());
                    TranslateContext<?> translateContext = new TranslateContext<>(
                            am.getRawType(),
                            annotations,
                            handler,
                            annotatedMember.getAnnotated()
                    );
                    TranslateName translateName = annotatedMember.getAnnotation(TranslateName.class);
                    if (translateName != null) {
                        translateContext.setTranslateName(translateName.value());
                    }
                    return new TranslateSerializer<>(translateContext, annotation);
                }

                // 格式化
                JsonFormat jsonFormat = getAnnotation(JsonFormat.class, annotation);
                if (jsonFormat != null) {
                    if (LocalDate.class.isAssignableFrom(rawType)) {
                        return new SLocalDateSerializer(jsonFormat.pattern());
                    }
                    if (LocalTime.class.isAssignableFrom(rawType)) {
                        return new SLocalTimeSerializer(jsonFormat.pattern());
                    }
                    if (LocalDateTime.class.isAssignableFrom(rawType)) {
                        return new SLocalDateTimeSerializer(jsonFormat.pattern());
                    }
                    if (Date.class.isAssignableFrom(rawType)) {
                        return new SDateSerializer(jsonFormat.pattern());
                    }
                    if (Number.class.isAssignableFrom(rawType)) {
                        return new DecimalSerializer(jsonFormat.pattern());
                    }
                }

            }
        }

        return super.findSerializer(am);
    }

    @JsonSerialize
    @Override
    public Object findDeserializer(Annotated am) {
        if (am instanceof AnnotatedMember) {
            AnnotatedMember annotatedMember = (AnnotatedMember) am;
            Class<?> rawType;
            if (annotatedMember instanceof AnnotatedMethod) {
                rawType = ((AnnotatedMethod) annotatedMember).getRawParameterType(0);
            } else {
                rawType = am.getRawType();
            }
            Iterable<Annotation> annotationIterable = annotatedMember.getAllAnnotations().annotations();
            List<Annotation> annotationList = new ArrayList<>();
            annotationIterable.forEach(annotationList::add);
            Annotation[] annotations = annotationList.toArray(new Annotation[0]);
            for (Annotation annotation : annotations) {
                Deserializer deserializer = getAnnotation(Deserializer.class, annotation);
                if (deserializer != null) {
                    PlusDeserializer jsonDeserializer = ReflectUtil.newInstance(deserializer.value());
                    jsonDeserializer.init(annotation, am);
                    return jsonDeserializer;
                }

                // 格式化
                JsonFormat jsonFormat = getAnnotation(JsonFormat.class, annotation);
                if (jsonFormat != null) {
                    if (LocalDate.class.isAssignableFrom(rawType)) {
                        return new SLocalDateDeserializer(jsonFormat.pattern());
                    }
                    if (LocalTime.class.isAssignableFrom(rawType)) {
                        return new SLocalDateDeserializer(jsonFormat.pattern());
                    }
                    if (LocalDateTime.class.isAssignableFrom(rawType)) {
                        return new SLocalDateTimeDeserializer(jsonFormat.pattern());
                    }
                    if (Date.class.isAssignableFrom(rawType)) {
                        return new SDateDeserializer(jsonFormat.pattern());
                    }
                    if (Number.class.isAssignableFrom(rawType)) {
                        return new DecimalDeserializer(jsonFormat.pattern());
                    }
                }

                // 翻译
/*                Translate translate = getAnnotation(Translate.class, annotation);
                if (translate != null) {
                    TranslateContext<?> translateContext = new TranslateContext<>(
                            rawType,
                            annotations,
                            SoarBeanUtils.getBean(translate.value())
                    );
                    translateContext.setAnnotated(annotatedMember.getAnnotated());
                    TranslateName translateName = annotatedMember.getAnnotation(TranslateName.class);
                    if (translateName != null) {
                        translateContext.setTranslateName(translateName.value());
                    }
                    return new TranslateDeserializer<>(translateContext, annotation);
                }*/

            }
        }
        return super.findDeserializer(am);
    }


    private <A extends Annotation>A getAnnotation(Class<A> aClass, Annotation annotation) {
        Class<? extends Annotation> annotationType = annotation.annotationType();
        if (aClass.isAssignableFrom(annotationType)) {
            return (A) annotation;
        }
        return annotationType.getAnnotation(aClass);
    }
}
